package com.chinaway.mobile.authcode.util;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileSelector;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.VFS;


/**
 * 图片读取、写入、切割工具类。
 * 
 */
public class Tools implements Runnable{
	private static final Log log = LogFactory.getLog(Tools.class);
	private static HashMap<String, Map<BufferedImage, String>> fileMap = null;
	
    /**
     * 将图片写入磁盘文件
     * 
     * @param imgFile 文件路径
     * @param bi BufferedImage 对象
     * @return 无
     */
    public static void writeImageToFile(String imgFile, BufferedImage bi) {
        // 写图片到磁盘上
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(imgFile.substring(imgFile.lastIndexOf('.') + 1));
        ImageWriter writer = (ImageWriter) writers.next();
        // 设置输出源
        File f = new File(imgFile);
        ImageOutputStream ios;
        try {
            ios = ImageIO.createImageOutputStream(f);
            writer.setOutput(ios);
            // 写入到磁盘
            writer.write(bi);
            ios.close();
        } catch (Exception e) {
        }
    }

    /**
     * 将一个像素点转为白色或者黑色。
     * 
     * @param pixel
     * @return 转换后的像素点（黑/白）
     */
    public static int pixelConvert(int pixel) {
        int result = 0;

        //获取R/G/B
        int r = (pixel >> 16) & 0xff;
        int g = (pixel >> 8) & 0xff;
        int b = (pixel) & 0xff;

        //默认黑色
        result = 0xff000000;

        int tmp = r * r + g * g + b * b;
        if (tmp > 3 * 130 * 130) {
            //白色，全F
            result =  0x00ffffff;
        }

        return result;
    }
    /**
     * 将一个像素点转为指定颜色
     * @param pixel
     * @return 转换后的像素点（指定颜色）
     */
    public static int pixelConvert(int pixel,int rgb) {
        //获取R/G/B
        int r = (pixel >> 16) & 0xff;
        int g = (pixel >> 8) & 0xff;
        int b = (pixel) & 0xff;

        int tmp = r * r + g * g + b * b;
        if(tmp>4000){
        	tmp = rgb ;
        }
        return tmp ;
    }

    /**
     * 获取图片
     * @param path
     * @return
     */
    public static BufferedImage getImage(String path) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(new File(path));
        } catch (IOException e) {
        }

        return image;
    }

    
    
    public static int isWhite(int colorInt) {
		Color color = new Color(colorInt);
		if (color.getRed() + color.getGreen() + color.getBlue() > 100) {
			return 1;
		}
		return 0;
	}
    public static int isBlack(int colorInt) {
		Color color = new Color(colorInt);
		if (color.getRed() + color.getGreen() + color.getBlue() <= 300) {
			return 1;
		}
		return 0;
	}
    public static String getSingleCharOcr(BufferedImage img, Map<BufferedImage, String> map) {
		String result = "";
		int width = img.getWidth();
		int height = img.getHeight();
		int maxhit = 0;
		for (BufferedImage bi : map.keySet()) {
			if(bi.getWidth()!=width)continue;
			int count = 0;//命中次数
			int count_bi = 0;
			int count_img = 0 ;
			for (int x = 0; x <  width; x++) {
				for (int y = 0; y <  height; y++) {
					 int bi_black = isBlack(bi.getRGB(x, y)) ;
					 int img_black = isBlack(img.getRGB(x, y));
						if(bi_black == 1){
							count_bi++ ;
							if(img_black==1){
								count++;
							}
						}
						if(img_black == 1){
							count_img++ ;
						}
				}
			}
			if (Math.abs(count_bi - count) < 4 && Math.abs(count_img - count_bi)<4) {//只能相差不大于3个像素
				if(count>maxhit){
					result = map.get(bi);
					maxhit = count;
				 }
			}
		}
		return result;
	}
    public static String getZjSingleCharOcr(BufferedImage img, Map<BufferedImage, String> map) throws Exception {
		String result = "#";
		int width = img.getWidth();
		int height = img.getHeight();
		int maxhit = 0;
		for (BufferedImage bi : map.keySet()) {
			int count = 0;//命中次数
			int count_bi = 0;
			for (int x = 0; x <  width; x++) {
				for (int y = 0; y <  height; y++) {
					 int bi_black = isBlack(bi.getRGB(x, y)) ;
					 int img_black = isBlack(img.getRGB(x, y));
						if(bi_black == 1){
							count_bi++ ;
							if(img_black==1){
								count++;
							}
						}
				}
			}
			if (Math.abs(count_bi - count) < 3) {//只能相差不大于3个像素
				if(count>maxhit){
					result = map.get(bi);
					maxhit = count;
				 }
				
			}
			 
		}
		return result;
	}
	
	public static Map<BufferedImage, String> loadTrainData(String name){
		if (!fileMap.containsKey(name)) {
			initImage();
		} 
		return  fileMap.get(name);
 
	}
	

	
	/**
     * 将一张图片按照规则切分为N张
     * @param image
     * @return
     */
    public static BufferedImage[] getCheckCodes(BufferedImage image,int num) {
        BufferedImage checkCode[] = new BufferedImage[num];
        int height = image.getHeight();
        int width = image.getWidth();
        for(int i = 0 ;i<num;i++){
        	checkCode[i]  = image.getSubimage(i * (width / checkCode.length), 0, width/ checkCode.length,  height);
        }
        return checkCode;
    }
    /**
     *   将 浙江验证码按照规则切分
     * @param image
     * @return
     */
	public static BufferedImage[] getZjCheckCodes(BufferedImage image) {
		BufferedImage checkCode[] = new BufferedImage[5];
		int height = image.getHeight();
		checkCode[0] = image.getSubimage(1, 0, 14, height);
		checkCode[1] = image.getSubimage(16, 0, 14, height);
		checkCode[2] = image.getSubimage(27, 0, 14, height);
		checkCode[3] = image.getSubimage(40, 0, 14, height);
		checkCode[4] = image.getSubimage(51, 0, 14, height);
		return checkCode;
	}
	
    /**
     *  将山东验证码 图片按照规则切分
     * @param image
     * @return
     */
	public static BufferedImage[] getSdCheckCodes(BufferedImage image) {
		BufferedImage checkCode[] = new BufferedImage[4];
		checkCode[0] = image.getSubimage(7,  5, 11,  15);
		checkCode[1] = image.getSubimage(19, 5, 11,  15);
		checkCode[2] = image.getSubimage(30, 5, 11,  15);
		checkCode[3] = image.getSubimage(41, 5, 11,  15);
		return checkCode;
	}
	private static void initImage(){
		URL url = Tools.class.getProtectionDomain().getCodeSource().getLocation();
		if(fileMap==null){
			fileMap = new HashMap<String,Map<BufferedImage, String>>();
		}
		try {
			Map<BufferedImage, String> sdmap = new HashMap<BufferedImage, String>(); 
			Map<BufferedImage, String> zjmap = new HashMap<BufferedImage, String>(); 
			FileSelector ff = new FileSelector() {
				public boolean includeFile(FileSelectInfo fileInfo)throws Exception {
					FileObject fo = fileInfo.getFile();
					return fo.getName().getBaseName().endsWith(".bmp") ;
				}
				public boolean traverseDescendents(FileSelectInfo fileInfo)
						throws Exception {
					return true;
				}
			};
			// 获得文件系统管理器
			FileSystemManager fsManager = VFS.getManager();
			String u = url.toString();
			if(StringUtils.startsWith(u, "file:plugins")){
				u = StringUtils.substringAfter(u, "file:");
				String[] ss = {"/u01/felix/",u};
				u = StringUtils.join(ss);
			}
			if (log.isInfoEnabled())
				log.info("u:" + u + " url:" + url.getPath());
			FileObject jarFile = fsManager.resolveFile("jar:" + u);
			
			FileObject[] arrfo =jarFile.findFiles(ff);
			for(FileObject fo:arrfo){
				FileName foname = fo.getName();
				String baseName = foname.getBaseName();
				InputStream is = fo.getContent().getInputStream();
				if(foname.getPath().indexOf("sd")>-1){
					sdmap.put(ImageIO.read(is), baseName.charAt(0) + "") ;
				}
				else if(foname.getPath().indexOf("zj")>-1){
					zjmap.put(ImageIO.read(is), baseName.charAt(0) + "") ;
				}
				
			}
			fileMap.put("sd", sdmap);
			fileMap.put("zj", zjmap);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private ExecutorService executor;
	@Override
	public void run() {
		log.info("开始加载山东验证码");
		long start = System.currentTimeMillis();
		initImage();
		log.info("结束加载山东验证码,耗时:" + (System.currentTimeMillis() - start) +"ms");
	}
	/**
	 * 任务初始化函数.
	 */
	public void start() {
		executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
			public Thread newThread(Runnable runable) {
				return new Thread(runable, "ImageTool");
			}
		});
		executor.execute(this);
		executor.shutdown();
	}
	
	//获得jar目录下的图片
    public static void main(String args[]){
//    	Map<BufferedImage, String> map  = new HashMap<BufferedImage, String>();
//    	try {
//			String path = "E:\\ChinaWay\\Felix\\bundle\\chinawa.mobile.mobileService_1.0.0.jar";
//			JarFile jarFile = new JarFile(path);
//			Enumeration<JarEntry> entrys = jarFile.entries();
//			while (entrys.hasMoreElements()) {
//				JarEntry jar = entrys.nextElement();
//				if(jar.isDirectory()){
//					continue;
//				}
//				String jarname = jar.getName();
//				
//				if(jarname.indexOf("train/zj")>-1){
//					String[] array_name = jarname.split("/");
//					BufferedImage bi = process(jarFile, jar);
//					map.put(bi, array_name[2].charAt(0) + "");
//				}
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		for(BufferedImage bi: map.keySet()){
//			System.out.println(map.get(bi));
//		}
    	
		try {
			FileSystemManager fsManager = VFS.getManager();
			FileObject jarFile = fsManager.resolveFile( "jar:" );
			System.out.println(jarFile.getURL().getPath());
			
		} catch (FileSystemException e) {
			e.printStackTrace();
		}
    	

    }
 
}	
